package ace.module.oauth2.server.core.impl.authentication.ace.factory.impl;

import ace.cmp.openfeign.core.AceFeignClientBuilder;
import ace.module.oauth2.callback.contract.feign.Oauth2AceAuthenticationCallbackFeign;
import ace.module.oauth2.callback.contract.feign.Oauth2AceAuthorizationCallbackFeign;
import ace.module.oauth2.server.api.callback.Oauth2AceAuthenticationCallbackApi;
import ace.module.oauth2.server.api.callback.Oauth2AceAuthorizationCallbackApi;
import ace.module.oauth2.server.api.enums.Oauth2RegisteredClientAuthConfigApiImplTypeEnum;
import ace.module.oauth2.server.api.enums.Oauth2RegisteredClientAuthConfigFeignRequestInterceptorStatusEnum;
import ace.module.oauth2.server.core.impl.authentication.ace.Interceptor.Oauth2RestRequestInterceptorHolder;
import ace.module.oauth2.server.core.impl.authentication.ace.factory.CallbackApiFeignFactory;
import ace.module.oauth2.server.core.impl.dao.entity.Oauth2RegisteredClientAuthConfig;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.openfeign.FeignClientBuilder;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

/**
 * 认证实现接口工厂.
 *
 * @author caspar
 */
@AllArgsConstructor
@Component
public class CallbackApiFeignFactoryImpl implements CallbackApiFeignFactory {

  private final AceFeignClientBuilder feignClientBuilder;

  private final Oauth2RestRequestInterceptorHolder oauth2RestRequestInterceptorHolder;

  @Override
  public Oauth2AceAuthenticationCallbackApi getOrCreateAuthCallbackApi(Oauth2RegisteredClientAuthConfig oauth2RegisteredClientAuthConfig) {

    Assert.isTrue(Oauth2RegisteredClientAuthConfigApiImplTypeEnum.REST.getCode().equals(oauth2RegisteredClientAuthConfig.getApiImplType()),
        "仅支持rest类型接口创建"
    );

    try {

      String feignName = oauth2RegisteredClientAuthConfig.getFeignName();
      FeignClientBuilder.Builder<Oauth2AceAuthenticationCallbackFeign> builder = this.feignClientBuilder.forType(Oauth2AceAuthenticationCallbackFeign.class, feignName);

      if (Oauth2RegisteredClientAuthConfigFeignRequestInterceptorStatusEnum.INTERNAL_SERVER.getCode().equals(oauth2RegisteredClientAuthConfig.getFeignRequestInterceptorStatus())) {
        builder.customize(
            feignClientBuilder -> {
              feignClientBuilder.requestInterceptor(this.oauth2RestRequestInterceptorHolder.getDelegatingRequestInterceptor());
            }
        );
      }

      if (StringUtils.isNotEmpty(oauth2RegisteredClientAuthConfig.getCallbackUrl())) {
        builder.url(oauth2RegisteredClientAuthConfig.getCallbackUrl());
      }

      return builder.build();
    } catch (Throwable ex) {
      throw new RuntimeException(String.format("获取[%s]类型 feign失败", Oauth2AceAuthenticationCallbackApi.class.getName()), ex);
    }
  }

  @Override
  public Oauth2AceAuthorizationCallbackApi getOrCreateUserInfoCallbackApi(Oauth2RegisteredClientAuthConfig oauth2RegisteredClientAuthConfig) {
    Assert.isTrue(Oauth2RegisteredClientAuthConfigApiImplTypeEnum.REST.getCode().equals(oauth2RegisteredClientAuthConfig.getApiImplType()),
        "仅支持rest类型接口创建"
    );

    try {

      String feignName = oauth2RegisteredClientAuthConfig.getFeignName();
      FeignClientBuilder.Builder<Oauth2AceAuthorizationCallbackFeign> builder = this.feignClientBuilder.forType(Oauth2AceAuthorizationCallbackFeign.class, feignName);

      if (Oauth2RegisteredClientAuthConfigFeignRequestInterceptorStatusEnum.INTERNAL_SERVER.getCode().equals(oauth2RegisteredClientAuthConfig.getFeignRequestInterceptorStatus())) {
        builder.customize(
            feignClientBuilder -> {
              feignClientBuilder.requestInterceptor(this.oauth2RestRequestInterceptorHolder.getDelegatingRequestInterceptor());
            }
        );
      }

      if (StringUtils.isNotEmpty(oauth2RegisteredClientAuthConfig.getCallbackUrl())) {
        builder.url(oauth2RegisteredClientAuthConfig.getCallbackUrl());
      }

      return builder.build();
    } catch (Throwable ex) {
      throw new RuntimeException(String.format("获取[%s]类型 feign失败", Oauth2AceAuthorizationCallbackApi.class.getName()), ex);
    }
  }


}
